home *** CD-ROM | disk | FTP | other *** search
- /********************************************************
- int24.c
-
- (C) 1990 Joel Spolsky, All Rights Reserved.
-
- This code is released into the public domain by the author.
- You can do whatever you want with it. Please let me know
- if you find it useful or if you find any bugs.
- *********************************************************/
-
- /** int24.c
- **
- ** Interrupt 24 Handler version 0.9
- **
- ** When DOS has trouble accessing a peripheral it
- ** calls Interrupt 0x24. This is usually a pointer to
- ** the code in COMMAND.COM that prints the "Abort, Retry,
- ** Ignore" message. This is a completely portable module
- ** that replaces that message with a slightly more aesthetic
- ** one.
- **
- ** To use it, just call install_24(). To restore the DOS
- ** handler, call uninstall_24(). Warning! If you ever go
- ** into graphics mode of some sort, uninstall this! It won't
- ** be able to deal with a graphics screen correctly.
- **
- ** Note: We don't let the user ignore the error, which they shouldn't
- ** be doing anyway.
- **
- ** HISTORY
- ** -------
- ** 19 Mar 90 Created JS
- ** 16 Apr 90 Fixed to eliminate call to bioskey, which was reentering DOS
- **/
-
- #include <bios.h>
- #include <dos.h>
- #include <stdio.h>
-
- #define CRIT_ERROR_HANDLER (0x24)
-
- /** FUNCTION PROTOTYPES **/
- void install_24(void);
- void uninstall_24(void);
- void interrupt handle_24 (unsigned bp, unsigned di, unsigned si,
- unsigned ds, unsigned es, unsigned dx,
- unsigned cx, unsigned bx, unsigned ax);
- void fastprintz(int x, int y, int attr, char *s);
- int getbioskey(void);
-
- void interrupt (*oldvect)();
- unsigned scr; /* The segment where the screen is */
-
- /** install_24
- **
- ** Installs the fancy interrupt handler.
- **/
-
- void install_24(void)
- {
- oldvect = getvect(CRIT_ERROR_HANDLER); /* save old handler */
- setvect(CRIT_ERROR_HANDLER, handle_24); /* and install ours */
-
- /* Find out if the screen is at 0xB000 or 0xB800 */
- _AH = 0x0F;
- geninterrupt (0x10);
- if (_AL == 7)
- scr = 0xB000;
- else
- scr = 0xB800;
- }
-
-
- void uninstall_24(void)
- {
- /* Restore old handler */
- setvect(CRIT_ERROR_HANDLER, oldvect);
- }
-
- static char screen_buf[9][52]; /* room for the saved part of screen */
-
- void interrupt handle_24 (unsigned bp, unsigned di, unsigned si,
- unsigned ds, unsigned es, unsigned dx,
- unsigned cx, unsigned bx, unsigned ax)
- {
-
- int err,key,ret=-1;
- int r,c,start;
-
- err = di & 0x00FF; /* Error message, from DOS. */
-
- /* Save section of screen that will be overwritten */
- for (r=8; r<17; r++) {
- start = (160 * r + 54);
- for (c=0; c<26; c++) {
- screen_buf[r-8][c*2] = peekb(scr, start++);
- screen_buf[r-8][c*2+1] = peekb(scr, start++);
- }
- }
-
- /* Pop up error message */
- fastprintz( 8,27,0x07,"╓────────────────────────╖");
- fastprintz( 9,27,0x07,"║Error! ║");
- fastprintz(10,27,0x07,"║ ║");
-
- /* Common diagnosable problems */
- switch(err) {
- case 0x00:
- fastprintz(11,27,0x07,"║Disk is write protected.║"); break;
- case 0x02:
- fastprintz(11,27,0x07,"║Disk drive is not ready.║"); break;
- default:
- fastprintz(11,17,0x07,"║Disk error. ║"); break;
- }
-
- fastprintz(12,27,0x07,"║ ║");
- fastprintz(13,27,0x07,"║ Try again ║");
- fastprintz(13,29,0x0f,"T");
- fastprintz(14,27,0x07,"║ Exit this program ║");
- fastprintz(14,29,0x0f,"E");
-
- /* In DOS 3.00 and later, they can also fail the disk access */
- if (_osmajor > 2) {
- fastprintz(15,27,0x07,"║ Cancel this operation ║");
- fastprintz(15,29,0x0f,"C");
- }
- else
- fastprintz(15,27,0x07,"║ ║");
-
- fastprintz(16,27,0x07,"╙────────────────────────╜");
-
- /* Call BIOS to get a single keystroke from the user */
- do {
- key=getbioskey();
-
- if (key & 0x00FF)
- key &= 0x00FF;
-
- switch(key) {
- case 't': case 'T': ret = 0x0001; break;
- case 'e': case 'E': ret = 0x0002; break;
- case 'c': case 'C': if (_osmajor > 2) ret = 0x0003; break;
- default: break;
- }
-
- } while (ret < 0);
-
- /* Restore that section of the screen */
- for (r=8; r<17; r++) {
- start = (160*r + 54);
- for (c=0; c<26; c++) {
- pokeb(scr, start++, screen_buf[r-8][c*2]);
- pokeb(scr, start++, screen_buf[r-8][c*2+1]);
- }
- }
-
- ax = ret;
- /* And please don't tell me I didn't use any of those parameters. */
- #pragma warn -par
- }
- #pragma warn .par
-
-
- /* fastprintz - shove an asciz string onto the screen */
- void
- fastprintz(int y, int x, int attr, char *s)
- {
- int i=0,base;
-
- base = (80*y+x)<<1; /* determine offset into screen */
- while (s[i]!=0) {
- pokeb(scr, base++, s[i++]);
- pokeb(scr, base++, attr);
- }
- }
-
- /** getbioskey
- **
- ** get one key from the BIOS
- **
- ** Like TC bioskey(0), but doesn't nab control Break. It seems
- ** that the TC bioskey was trying to block Ctrl-Breaks, which
- ** it did by changing the Ctrl-Break handler, which it called
- ** DOS to do. This made the interrupt handler reenter DOS which
- ** is illegal.
- **/
-
- int getbioskey(void)
- {
- union REGS regs;
- struct SREGS segregs;
-
- segread(&segregs);
- regs.h.ah = 0;
- int86x (0x16, ®s, ®s, &segregs);
- return regs.x.ax;
- }
-
-